package com.cfx.exercise_43;

import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Properties;

import org.junit.Test;

/*
 * java程序的运行氛围两种状态：
 * 编译时：通过javac命令，生成一个或多个，生成一个或多个.class文件。
 * 运行时：通过Java命令，将一个或多个.class字节码文件加载到内存中。（JVM提供的类加载器完成）
 * 
 * 反射之前：
 * 在编译时我们就能确定创建什么类的对象，操作什么属性，调用什么方法
 * 
 * 某种情况下，我们需要得知并使用一个在编译时完全未知的类，然后创建其对象，调用其属性和方法
 * 
 * 反射机制：被视为动态语言的关键，可以在运行时获取任何类的对象
 * 			在运行时操作任何类的属性，调用任何对象的方法
 * 
 */

public class TestRelection {

	@Test
	public void test() throws Throwable{
		//通过运行时类的属性class
		Class cl = Employee.class;
		//通过newInstance默认调用无参构造器。。
		Object object = cl.newInstance();
		Employee e = (Employee) object;
		System.out.println(e);
		//通过运行时类的getClass方法
		Employee emp = new Employee();
		Class<? extends Employee> cla1 = emp.getClass();
		
		//通过Class 类中的静态方法forName(String className)
		String className = "com.cfx.exercise_43.Employee";
		Class cla2 = Class.forName(className);
		
		//通过类加载器
		ClassLoader cl1 = this.getClass().getClassLoader();
		Class cla3 = cl1.loadClass(className);
		System.out.println(cl+"\n"+cla1+"\n"+cla2+"\n"+cla3);
		
	}
	
	@Test
	public void test1 () throws Throwable{
		Properties prop = new Properties();
		ClassLoader cl = this.getClass().getClassLoader();
		InputStream inputStream = cl.getResourceAsStream("jdbc.properties");
		prop.load(inputStream);
		String userName = prop.getProperty("prop.userName");
		System.out.println(userName);
	}
	@Test
	public void test2(){
	 	//在运行时获取运行时类的父类
		Class clazz = Employee.class;
		Class superclass = clazz.getSuperclass();
		//System.out.println(superclass.getName());
		
		//在运行时获取运行时类带泛型的父类类型
		Class cl1 = Employee.class;
		Type type = cl1.getGenericSuperclass();
		//System.out.println(type);
		
		//在运行时获取运行时类带泛型父类的泛型类型
		Class cl2 = Employee.class;
		//①获取带泛型的父类类型
		Type type2 = cl2.getGenericSuperclass();
		//②参数化类型
		ParameterizedType pt = (ParameterizedType)type2;
		//③获取真实参数类型的数组
		Type[] types = pt.getActualTypeArguments();
		
		for (Type ty : types) {
			//System.out.println(ty);
			//Class c = (Class)ty;
			//System.out.println(ty.getTypeName());//java1.8新增
		}
		//在运行时获取运行时类的接口
		Class cl3 = Employee.class;
		Class[] interfaces = cl3.getInterfaces();
		for (Class class1 : interfaces) {
			//System.out.println(class1);
		}
		//在运行时获取运行时类的内部类
		Class[] classes = cl1.getClasses();
		Class[] classes2 = cl1.getDeclaredClasses();
		//在运行时获取运行时类的包
		
		//在运行时获取运行时类的的注解
		Field[] fields = cl1.getDeclaredFields();
		for (Field field : fields) {
			Annotation[] annotations = field.getAnnotations();
			for (Annotation annotation : annotations) {
				if(annotation!=null){
					System.out.println(annotation);
				}
			}
		}
	}
}
	
		
			

